#ifndef _GAME_H_
#define _GAME_H_

#include <stack>

#include <SFML/Graphics.hpp>

class GameState;


///////////////////////////////////////////////////////
/// \brief Class representing the game.
///
/// Creates the main window of the game.
/// This class is responsible for managing the different
/// states of the game.
///////////////////////////////////////////////////////
class Game
{
public:
    ///////////////////////////////////////////////////////
    /// \brief Default contructor.
    ///
    /// Creates the window of the game, and set the first
    /// state as "InMenuState".
    ///////////////////////////////////////////////////////
    Game();

    ///////////////////////////////////////////////////////
    /// \brief Destructor.
    ///
    /// Destroys the window and the states of the game.
    ///////////////////////////////////////////////////////
    ~Game();

    ///////////////////////////////////////////////////////
    /// \brief Initializes the states of the game.
    ///
    ///////////////////////////////////////////////////////
    void init();

    ///////////////////////////////////////////////////////
    /// \brief Clears the states stack.
    ///
    ///////////////////////////////////////////////////////
    void clean();

    ///////////////////////////////////////////////////////
    /// \brief Handles the events according to the current
    /// state.
    ///
    ///////////////////////////////////////////////////////
    void handleEvents();

    ///////////////////////////////////////////////////////
    /// \brief Updates the game content according to the
    /// current state.
    ///
    ///////////////////////////////////////////////////////
    void update();

    ///////////////////////////////////////////////////////
    /// \brief Renders the game content according to the
    /// current state.
    ///
    ///////////////////////////////////////////////////////
    void render();

    ///////////////////////////////////////////////////////
    /// \brief Tells whether or not the game is running.
    ///
    ///
    /// \return True if the game is still running
    ///
    ///////////////////////////////////////////////////////
    bool isRunning() const;

    ///////////////////////////////////////////////////////
    /// \brief Change the state of the game (reset the old
    ///        one and add the new one)
    ///
    /// This function must only be called when we don't
    /// need the old state anymore, and therefore we can
    /// reset it so it is ready for a later use
    ///
    /// \param newState The state in which the game must
    ///                 now be
    ///
    /// \note The states stack should not be empty here
    ///
    ///////////////////////////////////////////////////////
    void changeState(GameState* newState);

    ///////////////////////////////////////////////////////
    /// \brief Add a new state to the game
    ///
    /// Unlike Game::changeState(), the old state is not
    /// removed and is still present in the stack
    ///
    /// \param newState The new state to be added
    ///
    ///////////////////////////////////////////////////////
    void addState(GameState* newState);

private:
    sf::RenderWindow* window_;  ///< Window for game rendering
    std::stack<GameState*> states_;  ///< Stack used to manage the differents states of the game
};


#endif /* _GAME_H_ */
